package anatex.domain;

import org.springframework.context.ApplicationContext;
import org.springframework.roo.addon.entity.RooEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.validation.constraints.Size;
import anatex.domain.CustomLocale;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;
import javax.persistence.TypedQuery;
import org.apache.tika.*;
import org.apache.tika.exception.TikaException;
import org.apache.tiles.servlet.context.ServletUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.Random;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import org.springframework.web.context.ContextLoaderListener;
import anatex.domain.Users;
import anatex.domain.Task;
import javax.persistence.EntityManager;
import anatex.domain.DocumentDomain;
import javax.persistence.OneToOne;
import java.util.ArrayList;
import java.util.Set;
import anatex.domain.Keyword;
import java.util.HashSet;
import javax.persistence.ManyToMany;
import javax.persistence.CascadeType;

@RooJavaBean
@RooEntity(finders = { "findDocumentsByOwner" })
public class Document {

    @Size(min = 3, max = 255)
    private String title;

    @Size(min = 2, max = 1000000)
    private String content;

    @Size(max = 255)
    private String originalFilename;

    @Size(max = 255)
    private String systemFilename;

    private Long fileSize;

    @Size(max = 255)
    private String mimeType;

    @ManyToOne
    private CustomLocale customLocale;

    @ManyToOne
    private Users owner;

    @Transient
    private CommonsMultipartFile uploadedFile;

    @ManyToOne
    private DocumentDomain documentDomain;

    public void setContent(String content) {
        this.content = content;
    }

    public void setOriginalFilename(String originalFilename) {
        this.originalFilename = originalFilename;
    }

    public void setSystemFilename(String systemFilename) {
        this.systemFilename = systemFilename;
    }

    public void setFileSize(Long fileSize) {
        this.fileSize = fileSize;
    }

    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }

    public void setUploadedFile(CommonsMultipartFile file) {
        if (file.isEmpty()) return;
        this.uploadedFile = file;
        this.originalFilename = file.getOriginalFilename();
        this.fileSize = file.getSize();
        System.out.println(" Uploaded  this.fileName: " + this.originalFilename + " ,  " + file.getClass().getName());
        String realPath = ContextLoaderListener.getCurrentWebApplicationContext().getServletContext().getRealPath("/docs");
        String newFilename = new String(realPath + new Random().nextInt(999999999) + "_" + new Date().getTime());
        try {
            newFilename = File.createTempFile("anatext_", new String("_" + new Date().getTime()), new File(realPath)).toString();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        this.systemFilename = newFilename;
        try {
            InputStream in = file.getInputStream();
            FileOutputStream f = new FileOutputStream(newFilename);
            int ch = 0;
            while ((ch = in.read()) != -1) {
                f.write(ch);
            }
            f.flush();
            f.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Tika myTika = new Tika();
        myTika.setMaxStringLength(-1);
        File fileTika = new File(newFilename);
        try {
            this.mimeType = myTika.detect(fileTika);
        } catch (IOException e) {
            System.out.println("Can't detect type of " + this.originalFilename);
            e.printStackTrace();
        }
        try {
            this.content = myTika.parseToString(fileTika);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TikaException e) {
            System.out.println("Error parsing file " + this.originalFilename);
            e.printStackTrace();
        }
    }

    public static TypedQuery<Document> findDocumentsByOwnerLimited(Users owner, Integer firstResult, Integer maxResults) {
        if (owner == null) throw new IllegalArgumentException("The owner argument is required");
        EntityManager em = entityManager();
        TypedQuery<Document> q = em.createQuery("SELECT Document FROM Document AS document WHERE document.owner = :owner", Document.class);
        q.setParameter("owner", owner);
        q.setFirstResult(firstResult).setMaxResults(maxResults);
        return q;
    }

    public static long countDocumentsByOwner(Users owner) {
        return entityManager().createQuery("select count(o) from Document o WHERE o.owner = :owner", Long.class).setParameter("owner", owner).getSingleResult();
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getTitle()).append(", ");
        sb.append("File: ").append(getOriginalFilename());
        return sb.toString();
    }

    @Transactional
    public void persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.persist(this);
        Task task = new Task();
        task.setCurrentState(Task.EnumState.NOT_STARTED);
        task.setEnabled(true);
        task.setDocument(this);
        task.persist();
    }
}
